package com.youbff.task.core.task;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.quartz.SchedulerException;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

import com.youbff.task.cluster.dto.ServerInfoDTO;
import com.youbff.task.cluster.service.ClusterService;
import com.youbff.task.constant.Constant;
import com.youbff.task.constant.TaskContext;
import com.youbff.task.core.TaskDispatch;
import com.youbff.task.core.base.LeaderCornYml;
import com.youbff.task.utils.RedisUtil;

/**
 * 领导任务<br/>
 * 1.检查是否有心跳超时的客户端<br/>
 * 2.清洗心跳超时的客户端信息
 * @author lixuefeng
 * @email youbff@163.com
 * @time 2018年1月29日 上午10:45:10
 */
public class LeaderClusterTask implements Tasklet {
    private static final Logger logger = Logger.getLogger(LeaderClusterTask.class);
    private static RedisUtil redisUtil;
    private static ClusterService clusterService;
    private static TaskDispatch taskDispatch;
    private static LeaderCornYml leaderCornYml;
    private static Job clientClusterTask;
    //已经停止自己的心跳服务
    private static boolean isStopMyHeartBeatTask = false;

    @Override
    public RepeatStatus execute(StepContribution contribution,
            ChunkContext chunkContext) throws Exception {
        init();
        stopMyHeartBeatTask();
        clientInfoMaintain();
        return RepeatStatus.FINISHED;
    }
    
    private void init(){
        if(null == redisUtil){
            redisUtil = TaskContext.getApplicationContext().getBean(RedisUtil.class);
        }
        if(null == clusterService){
            clusterService = TaskContext.getApplicationContext().getBean(ClusterService.class);
        }
        if(null == taskDispatch){
            taskDispatch = TaskContext.getApplicationContext().getBean(TaskDispatch.class);
        }
        if(null == leaderCornYml){
            leaderCornYml = TaskContext.getApplicationContext().getBean(LeaderCornYml.class);
        }
        if(null == clientClusterTask){
            clientClusterTask = (Job) TaskContext.getApplicationContext().getBean("clientClusterTask");
        }
    }
    
    /**
     * 停止自己心跳服务
     * @author lixuefeng
     * @email youbff@163.com
     * @time 2018年2月1日 下午3:16:45
     */
    private void stopMyHeartBeatTask(){
        ServerInfoDTO currentServer = TaskContext.getServerInfo();
        String serverMsg = currentServer.getSerIp()+":"+currentServer.getPort()+"/"+currentServer.getSerName();
        if(!isStopMyHeartBeatTask){
            try {
                if(taskDispatch.isExistJob(currentServer.getSerName()) && 0 == currentServer.getIsLeader()){
                    logger.debug("自己本身心跳服务存在,"+serverMsg+",停止心跳服务！");
                    taskDispatch.removeJob(currentServer.getSerName());
                    isStopMyHeartBeatTask = true;
                    currentServer.setIsLeader(1);
                    TaskContext.setServerInfo(currentServer);
                    return;
                }else{
                    isStopMyHeartBeatTask = true;
                }
            } catch (SchedulerException e) {
                logger.error("自己本身心跳服务存在,"+serverMsg+",停止心跳服务出现异常！", e);
                throw new RuntimeException();
            }
        }
    }
    
    /**
     * 客户端信息维护
     * @author lixuefeng
     * @email youbff@163.com
     * @time 2018年1月30日 下午2:56:38
     */
    private void clientInfoMaintain(){
        //检查超时的客户端
        Map<Object,Object> clientMap = redisUtil.getHashMap(Constant.client_heartbeat_cache_key);
        long currentTime = System.currentTimeMillis();
        List<String> removeKeyList = new ArrayList<String>();
        for(Entry<Object, Object> entry : clientMap.entrySet()){
            Long heartbeatTime = (Long) entry.getValue();
            long rangeTime = currentTime-heartbeatTime;
            if(rangeTime >= 15000){
                //心跳时间超过15秒，客户端丢失
                removeKeyList.add((String) entry.getKey());
            }
        }
        if(removeKeyList.size() > 0){
            logger.info("客户端心跳丢失相关信息:"+removeKeyList.toString());
            clientInfoRinse(removeKeyList);
        }
    }
    
    /**
     * 客户端信息清洗
     * @author lixuefeng
     * @email youbff@163.com
     * @time 2018年1月30日 下午2:58:25
     * @param removeKeyList
     * @param removeKeyArray
     */
    private void clientInfoRinse(List<String> removeKeyList){
        clusterService.clearClusterInfo(removeKeyList);
        for(String key : removeKeyList){
            redisUtil.delHashMap(Constant.client_heartbeat_cache_key, key);
            redisUtil.delHashMap(Constant.client_info_cache_key, key);
        }
    }
}
